// Copyright (c) Microsoft Corporation.
// 
// Author: Vance Morrison
// Date: 4/2007

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Xml.Serialization.GeneratedAssembly;
using VSAddins;

/// <summary>
/// HyperAddinSettings is a trivial class that holds all persisted configuration state associated with the
/// HyperAddin.  It knows how to load and save this data to the HyperAddin.dll.config file (see
/// code:HyperAddinSettings.ConfigFileName)  You retrieve the settings from the
/// code:HyperAddinSettings.Default instance of this class.   
/// </summary>
public class HyperAddinSettings
{
    public bool Logging = true;             // Is debug logging on.
    public int WordWrapColumn = 110;        // The maximum number of characters on a line before word wrapping. 
    [XmlElement("UserCommand")]
    public HyperAddinCommand[] UserCommands;    

    /// <summary>
    /// Saves the current settings back to the code:ConfigFileName 
    /// </summary>
    public void Save()
    {
        string configFileName = ConfigFileName;
        try
        {
            Log.WriteLine("Saving preferences in " + configFileName);
            TextWriter writer = new StreamWriter(configFileName);
            // We use SGEN to generate the HyperAddinSettingsSerializer to avoid startup time penalty
            // XmlSerializer serializer = new XmlSerializer(typeof(HyperAddinSettings));
            XmlSerializer serializer = new HyperAddinSettingsSerializer();
            serializer.Serialize(writer, _default);
            writer.Close();
            Log.WriteLine("Sucessfully wrote " + configFileName);
        }
        catch (Exception e)
        {
            Log.WriteLineAlways("Error writing " + configFileName + ": " + e);
        }

    }

    /// <summary>
    /// Retrieves the default values for the configuration settings.  
    /// </summary>
    static public HyperAddinSettings Default
    {
        get
        {
            if (_default == null)
            {
                _default = new HyperAddinSettings();
                string configFileName = ConfigFileName;
                if (File.Exists(configFileName))
                {
                    try
                    {
                        TextReader reader = new StreamReader(configFileName);
                        // We use SGEN to generate the HyperAddinSettingsSerializer to avoid startup time penalty
                        // XmlSerializer serializer = new XmlSerializer(typeof(HyperAddinSettings));
                        XmlSerializer serializer = new HyperAddinSettingsSerializer();
                        _default = (HyperAddinSettings)serializer.Deserialize(reader);
                        reader.Close();
                    }
                    catch (Exception e)
                    {
                        _errorMessage = "Exception while reading " + configFileName + ".\r\n" + e;
                        _default = new HyperAddinSettings();
                        _default.Logging = true;        // Definately insure logging is on
                    }
                }
            }
            return _default;
        }
    }

    /// <summary>
    /// If there is a failure during config file read, it is put in ErrorMessage, because the logging is not
    /// yet on.  
    /// </summary>
    public static string ErrorMessage { get { return HyperAddinSettings._errorMessage; } }

    #region Private
    static private string ConfigFileName
    {
        get
        {
            Assembly me = Assembly.GetExecutingAssembly();
            string fileName = me.ManifestModule.FullyQualifiedName;
            string configFileName = fileName + ".config";
            return configFileName;
        }
    }
    private static HyperAddinSettings _default;
    private static string _errorMessage;
    #endregion
}


/// <summary>
/// Represents a user defined command.  It is just a container for the XML data. 
/// </summary>
public class HyperAddinCommand
{
    public HyperAddinCommand() { }
    public HyperAddinCommand(string Name, string CommandLine, string ShortCut)
    { 
        this.Name = Name; 
        this.CommandLine = CommandLine;
        this.ShortCut = ShortCut; 
    }

    [XmlAttribute]
    public string Name;
    [XmlText]
    public string CommandLine;
    [XmlAttribute]
    public string ShortCut;
}
